#include "PropertyManager.h"
#include <QtMath>
#include <QDebug>

class TransformPropertyType
{
};
Q_DECLARE_METATYPE(TransformPropertyType)

PropertyManager::PropertyManager(QObject *parent):
    QtVariantPropertyManager(parent)
{
    connect(this, &PropertyManager::valueChanged,
            this, &PropertyManager::slotValueChanged);
    connect(this, &PropertyManager::propertyDestroyed,
            this, &PropertyManager::slotPropertyDestroyed);
}

PropertyManager::~PropertyManager()
{

}

int PropertyManager::transformTypeId()
{
    //return qMetaTypeId<TransformPropertyType>();
    return QVariant::Transform;
}

void PropertyManager::slotValueChanged(QtProperty *property, const QVariant &value)
{
    if (m_transformMirrorToProperty.contains(property))
    {
        auto transformProperty = m_transformMirrorToProperty.value(property);
        auto transformValue = this->value(transformProperty).value<QTransform>();
        // FIXME
        Q_UNUSED(value)
        setValue(transformProperty, transformValue);
    }
    else if (m_transformRotationToProperty.contains(property))
    {
        auto transformProperty = m_transformMirrorToProperty.value(property);
        auto transformValue = this->value(transformProperty).value<QTransform>();
        // FIXME
        Q_UNUSED(value)
        setValue(transformProperty, transformValue);
    }
}

void PropertyManager::slotPropertyDestroyed(QtProperty *property)
{
    if (m_transformMirrorToProperty.contains(property))
    {
        auto tProperty = m_transformMirrorToProperty.value(property);
        m_propertyTotransformData[tProperty].mirror = nullptr;
        m_transformMirrorToProperty.remove(property);
    }
    else if (m_transformRotationToProperty.contains(property))
    {
        auto tProperty = m_transformRotationToProperty.value(property);
        m_propertyTotransformData[tProperty].rotation = nullptr;
        m_transformRotationToProperty.remove(property);
    }
}

QString PropertyManager::valueText(const QtProperty *property) const
{
    if (m_propertyTotransformData.contains(property))
    {
        QVariant variant = m_propertyTotransformData[property].value;
        Transform transform = variant.value<Transform>();
        return QString("(%1°%2)")
                .arg(transform.rotation)
                .arg(transform.mirror ? ", mirrored" : "");
    }
    return QtVariantPropertyManager::valueText(property);
}

void PropertyManager::initializeProperty(QtProperty *property)
{
    if (propertyType(property) == transformTypeId())
    {
        TransformData data;
        data.value = QVariant::fromValue<Transform>(Transform());

        data.rotation = addProperty(QVariant::Double);
        data.rotation->setPropertyName("Rotation");
        property->addSubProperty(data.rotation);
        m_transformRotationToProperty.insert(data.rotation, property);

        data.mirror = addProperty(QVariant::Bool);
        data.mirror->setPropertyName("Mirror");
        property->addSubProperty(data.mirror);
        m_transformMirrorToProperty.insert(data.mirror, property);

        m_propertyTotransformData.insert(property, data);
    }
    QtVariantPropertyManager::initializeProperty(property);
}

void PropertyManager::uninitializeProperty(QtProperty *property)
{
    if (propertyType(property) == transformTypeId())
    {
        TransformData data = m_propertyTotransformData.value(property);
        m_transformMirrorToProperty.remove(data.mirror);
        m_transformRotationToProperty.remove(data.rotation);
        m_propertyTotransformData.remove(property);
    }
    QtVariantPropertyManager::uninitializeProperty(property);
}

bool PropertyManager::isPropertyTypeSupported(int propertyType) const
{
    if (propertyType == transformTypeId())
        return true;
    return QtVariantPropertyManager::isPropertyTypeSupported(propertyType);
}

int PropertyManager::valueType(int propertyType) const
{
    if (propertyType == transformTypeId())
        return QVariant::Transform;
    return QtVariantPropertyManager::valueType(propertyType);
}

QVariant PropertyManager::value(const QtProperty *property) const
{
    if (m_propertyTotransformData.contains(property))
        return m_propertyTotransformData[property].value;
    return QtVariantPropertyManager::value(property);
}

void PropertyManager::setValue(QtProperty *property, const QVariant &value)
{
    if (m_propertyTotransformData.contains(property))
    {
        if (int(value.type()) != transformTypeId() && !value.canConvert(transformTypeId()))
            return;
        Transform transform = value.value<Transform>();
        TransformData &data = m_propertyTotransformData[property];
        data.value = QVariant::fromValue<Transform>(transform);
        data.mirror->setValue(transform.mirror);
        data.rotation->setValue(transform.rotation);

        emit propertyChanged(property);
        emit valueChanged(property, value);
        return;
    }
    QtVariantPropertyManager::setValue(property, value);
}
